package com.shopping_back.serviceImpl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.easysdk.factory.Factory;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.shopping_back.config.AliPayConfig;
import com.shopping_back.mapper.*;
import com.shopping_back.pojo.dto.PayDTO;
import com.shopping_back.pojo.dto.RechargeDTO;
import com.shopping_back.pojo.entity.*;
import com.shopping_back.service.IPayService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Service
@RequiredArgsConstructor
public class PayServiceImpl implements IPayService {
    private final SkuMapper skuMapper;
    private final SpuMapper spuMapper;
    private final UserProfileMapper userProfileMapper;
    private final OrderMainMapper orderMainMapper;
    private final OrderItemMapper orderItemMapper;
    private final PaymentRecordMapper paymentRecordMapper;
    private final DeliveryMapper deliveryMapper;
    private final UserAccountMapper   userAccountMapper;
    private final MerchantInfoMapper  merchantInfoMapper;
    private final MemberOrderMapper memberOrderMapper;
    private final AliPayConfig aliPayConfig;

    private static final Logger log = LoggerFactory.getLogger(PayServiceImpl.class);

    @Override
    public String createAlipayPage(PayDTO dto) throws Exception {
        String orderSn = dto.getOrderSn();

        // 取订单 & 校验
        OrderMain order = orderMainMapper.selectOne(
                Wrappers.<OrderMain>lambdaQuery()
                        .eq(OrderMain::getOrderSn, orderSn)
                        .eq(OrderMain::getStatus, 0));
        if (order == null) throw new IllegalArgumentException("订单不存在或已支付");
        String addr = StrUtil.trimToEmpty(dto.getReceiverAddr());
        if (StrUtil.isBlank(addr)) {
            throw new IllegalArgumentException("收货/自提地址不能为空");
        }

        saveDeliveryPref(order, dto);

        // 校验每个 item 库存（防止长时间挂单库存被抢光）
        List<OrderItem> items = orderItemMapper.selectList(
                Wrappers.<OrderItem>lambdaQuery().eq(OrderItem::getOrderId, order.getId()));
        for (OrderItem it : items) {
            Sku sku = skuMapper.selectById(it.getSkuId());
            if (sku.getStock() < it.getQuantity()) {
                throw new IllegalStateException("【" + sku.getId() + "】库存不足，请重新下单");
            }
        }

        // 发起支付宝（金额直接用 order.getPayAmount()）
        BigDecimal total = order.getPayAmount();
        String subject   = "订单 " + orderSn + " 支付";

        // 构造 Alipay SDK 客户端
        AlipayClient client = new DefaultAlipayClient(
                aliPayConfig.getGatewayUrl(),
                aliPayConfig.getAppId(),
                aliPayConfig.getAppPrivateKey(),
                "JSON", "utf-8",
                aliPayConfig.getAlipayPublicKey(),
                "RSA2"
        );

        AlipayTradePagePayRequest req = new AlipayTradePagePayRequest();
        req.setNotifyUrl(aliPayConfig.getNotifyUrl());
        req.setReturnUrl("http://testshop.free.idcfengye.com/api/pay/return");

        String bizContent = "{"
                + "\"out_trade_no\":\"" + orderSn + "\","
                + "\"total_amount\":\"" + total + "\","
                + "\"subject\":\"" + subject + "\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\""
                + "}";

        req.setBizContent(bizContent);

        // 打印调试日志
        log.info("▶▶▶ Alipay PAGE_PAY Request ▶▶▶");
        log.info("  Gateway URL : {}",              aliPayConfig.getGatewayUrl());
        log.info("  App ID      : {}",              aliPayConfig.getAppId());
        log.info("  Notify URL  : {}",              aliPayConfig.getNotifyUrl());
        log.info("  Out Trade No: {}",              orderSn);
        log.info("  Total Amount: {}",              total);
        log.info("  Subject     : {}",              subject);
        log.info("  BizContent  : {}",              bizContent);
        log.info("  SignType    : RSA2");
        log.info("  Charset     : utf-8");
        log.info("  Format      : JSON");

        return client.pageExecute(req).getBody();
    }

    /** ===================== 收件人 JSON ===================== */
    private String buildReceiverJson(Long userId, String addr) {
        UserAccount ua = userAccountMapper.selectById(userId);
        UserProfile up = userProfileMapper.selectById(userId);

        Map<String,Object> m = new HashMap<>();
        m.put("name",   up!=null && up.getRealName()!=null ? up.getRealName() : ua.getUsername());
        m.put("phone",  ua.getMobile());
        m.put("email",  ua.getEmail());
        m.put("address", addr);
        return new JSONObject(m).toString();
    }


    /** ===================== 发件人 / 商家 JSON ===================== */
    private String buildSenderJson(Long merchantUserId) {
        // ① 读取店铺信息
        MerchantInfo mi = merchantInfoMapper.selectById(merchantUserId);
        if (mi == null) throw new IllegalArgumentException("商家不存在");

        // ② 读取账号(电话 / 邮箱)
        UserAccount ua = userAccountMapper.selectById(merchantUserId);

        Map<String, Object> data = new HashMap<>();
        data.put("name",    mi.getShopName());       // 店铺名
        data.put("phone",   ua.getMobile());         // 联系电话
        data.put("email",   ua.getEmail());          // 联系邮箱
        data.put("address", mi.getAddress());        // 店铺地址

        return new JSONObject(data).toString();
    }


    @Override
    @Transactional
    public String handleAlipayNotify(HttpServletRequest request) throws Exception {
        Map<String,String> params = new HashMap<>();
        request.getParameterMap().forEach((k,v) -> params.put(k, request.getParameter(k)));

        // 验签 & 状态
        if (!"TRADE_SUCCESS".equals(params.get("trade_status"))
                || !Factory.Payment.Common().verifyNotify(params)) {
            return "fail";
        }
        String outNo = params.get("out_trade_no");

        if (outNo.startsWith("RECHARGE_")) {
            String[] parts = outNo.split("_");
            if (parts.length < 3) return "fail";
            Long userId = Long.valueOf(parts[1]);

            // 2‑1 钱包 + 金额
            BigDecimal amt = new BigDecimal(params.get("total_amount"));
            creditWallet(userId, amt);

            // 2‑2 写充值流水
            PaymentRecord rec = new PaymentRecord();
            rec.setOrderSn(outNo);
            rec.setPaySn(params.get("trade_no"));
            rec.setPayAmount(amt);
            rec.setPayChannel("ALIPAY_RECHARGE");
            rec.setStatus(true);
            rec.setCallbackData(params.toString());
            rec.setCreateTime(LocalDateTime.now());
            paymentRecordMapper.insert(rec);

            log.info("用户 {} 成功充值 {} 元", userId, amt);
            return "success";
        }


        if (outNo.startsWith("MEMBER_")) {
            Long orderId = Long.valueOf(outNo.substring(7));
            MemberOrder mOrder = memberOrderMapper.selectById(orderId);
            if (mOrder == null || mOrder.getStatus() != 0) return "success";

            BigDecimal amt = new BigDecimal(params.get("total_amount"));

            /* 2. 写支付流水 */
            PaymentRecord rec = new PaymentRecord();
            rec.setOrderSn(outNo);
            rec.setPaySn(params.get("trade_no"));
            rec.setPayAmount(amt);
            rec.setPayChannel("ALIPAY_MEMBER");
            rec.setStatus(true);
            rec.setCallbackData(params.toString());
            rec.setCreateTime(LocalDateTime.now());
            paymentRecordMapper.insert(rec);

            handleMemberPaySuccess(mOrder, amt);

            log.info("会员订单 {} 支付成功，已写流水", orderId);
            return "success";
        }

        String orderSn = outNo;
        System.out.println(orderSn);
        OrderMain order = orderMainMapper.selectOne(
                Wrappers.<OrderMain>lambdaQuery().eq(OrderMain::getOrderSn, orderSn));

        Delivery del = deliveryMapper.selectById(order.getId());
        if (del == null) {
            return "fail";
        }
        del.setSenderInfo(buildSenderJson(order.getMerchantId()));
//        del.setDeliverySn(UUID.randomUUID().toString().substring(0,18));
        del.setStatus(0);
        deliveryMapper.updateById(del);

        // 扣减库存 + 增加销量
        List<OrderItem> items = orderItemMapper.selectList(
                Wrappers.<OrderItem>lambdaQuery().eq(OrderItem::getOrderId, order.getId()));

        for (OrderItem it : items) {
            Sku sku = skuMapper.selectById(it.getSkuId());
            sku.setStock(sku.getStock() - it.getQuantity());
            sku.setSales((sku.getSales() == null ? 0 : sku.getSales()) + it.getQuantity());
            skuMapper.updateById(sku);
        }

        // 更新订单状态
        System.out.println("更新订单状态"+orderSn);
        orderMainMapper.update(
                null,
                Wrappers.<OrderMain>lambdaUpdate()
                        .eq(OrderMain::getOrderSn, orderSn)      // 按订单号匹配
                        .set(OrderMain::getStatus, 1)            // 已支付
                        .set(OrderMain::getPaymentTime, LocalDateTime.now())
        );

        // 记录支付流水
        PaymentRecord rec = new PaymentRecord();
        rec.setOrderSn(orderSn);
        rec.setPaySn(params.get("trade_no"));
        rec.setPayAmount(new BigDecimal(params.get("total_amount")));
        rec.setPayChannel("ALIPAY");
        rec.setStatus(true);
        rec.setCallbackData(params.toString());
        rec.setCreateTime(LocalDateTime.now());
        paymentRecordMapper.insert(rec);


//        del.setDeliverySn(UUID.randomUUID().toString().substring(0,18));


        return "success";
    }

    @Override
    public Sku getSkuById(Long skuId) {
        Sku sku = skuMapper.selectById(skuId);
        if (sku == null) throw new IllegalArgumentException("SKU 不存在");
        Spu spu = spuMapper.selectById(sku.getSpuId());
        if (spu != null) sku.setSpecsJson(spu.getTitle());
        return sku;
    }

    @Override
    @Transactional
    public String payWithBalance(PayDTO dto,Long userId) {
        String orderSn = dto.getOrderSn();

        System.out.println("订单号"+dto.getOrderSn());
        System.out.println("userId"+userId);
        OrderMain order = orderMainMapper.selectOne(
                Wrappers.<OrderMain>lambdaQuery()
                        .eq(OrderMain::getOrderSn, orderSn)
                        .eq(OrderMain::getUserId, userId)
                        .eq(OrderMain::getStatus, 0));

        if (order == null) throw new IllegalArgumentException("订单不存在或已支付");

        List<OrderItem> items = orderItemMapper.selectList(
                Wrappers.<OrderItem>lambdaQuery().eq(OrderItem::getOrderId, order.getId()));

        saveDeliveryPref(order, dto);

        /* 校验余额 */
        BigDecimal total = order.getPayAmount();
        UserProfile profile = userProfileMapper.selectById(userId);
        BigDecimal wallet = BigDecimal.valueOf(profile.getWallet()==null?0:profile.getWallet());
        if (wallet.compareTo(total) < 0) {
            throw new IllegalStateException("支付余额不足");
        }
        profile.setWallet(wallet.subtract(total).intValue());
        userProfileMapper.updateById(profile);

        /* 扣库存 + 加销量 */
        for (OrderItem it : items) {
            Sku sku = skuMapper.selectById(it.getSkuId());
            if (sku.getStock() < it.getQuantity()) {
                throw new IllegalStateException("库存不足，支付中止");
            }
            sku.setStock(sku.getStock() - it.getQuantity());
            sku.setSales((sku.getSales()==null?0:sku.getSales()) + it.getQuantity());
            skuMapper.updateById(sku);
        }

        /* 写支付流水 */
        PaymentRecord rec = new PaymentRecord();
        rec.setOrderSn(order.getOrderSn());
        rec.setPaySn(generatePaySn());
        rec.setPayAmount(total);
        rec.setPayChannel("BALANCE");
        rec.setStatus(Boolean.TRUE);
        rec.setCreateTime(LocalDateTime.now());
        paymentRecordMapper.insert(rec);

        /* 更新订单状态 */
        order.setStatus(1);
        order.setPaymentTime(LocalDateTime.now());
        orderMainMapper.updateById(order);

        /* 写 delivery */
        Delivery del = deliveryMapper.selectById(order.getId());
        if (del == null) {
            del = new Delivery();
            del.setOrderId(order.getId());
            del.setDeliveryType(dto.getDeliveryType()==null?1:dto.getDeliveryType());
            del.setReceiverInfo(buildReceiverJson(userId, dto.getReceiverAddr()));
            del.setStatus(-1);                     // 刚刚 saveDeliveryPref 失败的话兜底
            deliveryMapper.insert(del);
        }
        del.setSenderInfo(buildSenderJson(order.getMerchantId()));
//        del.setDeliverySn(UUID.randomUUID().toString().substring(0,18));
        del.setStatus(0);                       // 未发货
        deliveryMapper.updateById(del);

        return null;   // 前端收到 null 视为“支付成功，跳订单页”
    }

    @Override
    public Map<String, Object> getSimpleOrderInfo(String orderSn) {

        OrderMain order = orderMainMapper.selectOne(
                Wrappers.<OrderMain>lambdaQuery().eq(OrderMain::getOrderSn, orderSn));

        if (order == null) {
            throw new IllegalArgumentException("订单不存在");
        }

        // 明细
        List<OrderItem> items = orderItemMapper.selectList(
                Wrappers.<OrderItem>lambdaQuery().eq(OrderItem::getOrderId, order.getId()));

        // 只挑前端要用的字段
        List<Map<String,Object>> simpleItems = items.stream().map(it -> {
            Sku sku = skuMapper.selectById(it.getSkuId());
            Map<String,Object> m = new HashMap<>();
            m.put("skuId",    it.getSkuId());
            m.put("skuName",  it.getSkuName());
            m.put("quantity", it.getQuantity());
            m.put("price",    it.getSkuPrice());
            m.put("subtotal", it.getSubTotal());
            m.put("skuImage", sku != null ? sku.getSkuImage() : null);
            return m;
        }).toList();

        Map<String,Object> result = new HashMap<>();
        result.put("orderSn",       orderSn);
        result.put("status",        order.getStatus());
        result.put("payAmount",     order.getPayAmount());
        result.put("promotionAmt",  order.getPromotionAmount());
        result.put("items",         simpleItems);

        return result;
    }

    /**
     * 在用户点击“去支付”时保存配送偏好：
     *   - status = -1 表示 待付款
     *   - 如果用户重复点击，只 update 不会插重复
     */
    private void saveDeliveryPref(OrderMain order, PayDTO dto) {
        String addr = StrUtil.trimToEmpty(dto.getReceiverAddr());
        if (StrUtil.isBlank(addr)) {
            throw new IllegalArgumentException("收货/自提地址不能为空");
        }

        int dt = (dto.getDeliveryType() == null ? 1 : dto.getDeliveryType());

        Delivery del = deliveryMapper.selectById(order.getId());
        if (del == null) {                    // 第一次点击
            del = new Delivery();
            del.setOrderId(order.getId());
            del.setDeliveryType(dt);
            del.setReceiverInfo(buildReceiverJson(order.getUserId(), addr));
            del.setStatus(-1);
            deliveryMapper.insert(del);
        } else {                              // 后续重复点击
            del.setDeliveryType(dt);
            del.setReceiverInfo(buildReceiverJson(order.getUserId(), addr));
            // status 仍保持 -1
            deliveryMapper.updateById(del);
        }
    }




    private String generateAlipayPaymentUrl(String orderSn, BigDecimal total) {
        return "https://openapi.alipay.com/gateway.do?orderSn=" + orderSn;
    }

    private String generateAlipayRechargeUrl(Long userId, BigDecimal amount) {
        return "https://openapi.alipay.com/gateway.do?rechargeUser=" + userId + "&amount=" + amount;
    }

//    private OrderMain createOrder(Long userId, Sku sku, int quantity) {
//        Spu spu = spuMapper.selectById(sku.getSpuId());
//        BigDecimal total = sku.getPrice().multiply(BigDecimal.valueOf(quantity));
//
//        OrderMain order = new OrderMain();
//        order.setOrderSn(generateOrderSn());
//        order.setUserId(userId);
//        order.setTotalAmount(total);
//        order.setPayAmount(total);
//        order.setPromotionAmount(BigDecimal.ZERO);
//        order.setStatus(0);
//        order.setMerchantId(spu.getMerchantId());
//        order.setCreateTime(LocalDateTime.now());
//        orderMainMapper.insert(order);
//
//        OrderItem item = new OrderItem();
//        item.setOrderId(order.getId());
//        item.setSkuId(sku.getId());
//        item.setSkuName(spu.getTitle());
//        item.setSkuPrice(sku.getPrice());
//        item.setQuantity(quantity);
//        item.setSubTotal(total);
//        orderItemMapper.insert(item);
//
//        return order;
//    }

    @Override
    public String createRechargePage(Long userId, RechargeDTO dto) throws Exception {

        /* ---------- 1. 参数校验 ---------- */
        if (dto.getAmount() == null || dto.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("充值金额必须大于 0");
        }
        BigDecimal total = dto.getAmount();

        /* ---------- 2. 生成唯一交易号 ---------- */
        String outTradeNo = "RECHARGE_" + userId + "_" + System.currentTimeMillis();

        /* ---------- 3. 构造 Alipay Client ---------- */
        AlipayClient client = new DefaultAlipayClient(
                aliPayConfig.getGatewayUrl(),
                aliPayConfig.getAppId(),
                aliPayConfig.getAppPrivateKey(),
                "JSON", "utf-8",
                aliPayConfig.getAlipayPublicKey(),
                "RSA2"
        );

        AlipayTradePagePayRequest req = new AlipayTradePagePayRequest();
        req.setNotifyUrl(aliPayConfig.getNotifyUrl());
        req.setReturnUrl("http://testshop.free.idcfengye.com/api/pay/return");      // 复用已有 returnUrl

        /* ---------- 4. bizContent ---------- */
        String bizContent = "{"
                + "\"out_trade_no\":\"" + outTradeNo             + "\","
                + "\"total_amount\":\"" + total.toPlainString()  + "\","
                + "\"subject\":\"余额充值\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\""
                + "}";
        req.setBizContent(bizContent);

        /* ---------- 5. 调试日志 ---------- */
        log.info("▶▶▶ Alipay RECHARGE Request ▶▶▶");
        log.info("  Gateway URL : {}", aliPayConfig.getGatewayUrl());
        log.info("  Out Trade No: {}", outTradeNo);
        log.info("  Amount      : {}", total);
        log.info("  BizContent  : {}", bizContent);

        /* ---------- 6. 返回支付宝表单 ---------- */
        return client.pageExecute(req).getBody();
    }

    @Override
    public String createMemberPayPage(Long userId,
                                      Integer level,
                                      BigDecimal amount,
                                      Integer months) throws Exception {  // 新增months参数

        // 新增调试日志
        System.out.println("=== PayServiceImpl.createMemberPayPage ===");
        System.out.println("userId: " + userId);
        System.out.println("level: " + level + " (类型: " + (level != null ? level.getClass().getSimpleName() : "null") + ")");
        System.out.println("amount: " + amount);
        System.out.println("months: " + months);

        // 强化参数验证
        Integer validLevel = level;
        if (validLevel == null) {
            System.out.println("会员等级为null，使用默认值1");
            validLevel = 1;
        }

        if (validLevel < 1 || validLevel > 5) {
            System.out.println("会员等级验证失败: level=" + validLevel + " (原始值: " + level + ")");
            throw new IllegalArgumentException("会员等级必须 1‑5，当前值: " + validLevel);
        }

        // 新增months验证
        if (months == null || months < 1 || months > 12) {
            throw new IllegalArgumentException("购买月数必须 1-12");
        }

        MemberOrder mOrder = new MemberOrder();
        mOrder.setUserId(userId);
        mOrder.setLevel(validLevel);  // 使用验证后的等级
        mOrder.setAmount(amount);
        mOrder.setStatus(0);
        mOrder.setStartDate(LocalDate.now());  // 新增：设置开始日期
        mOrder.setEndDate(LocalDate.now().plusMonths(months));  // 新增：根据月数计算结束日期
        memberOrderMapper.insert(mOrder);


        String outTradeNo = "MEMBER_" + mOrder.getId();

        AlipayClient client = new DefaultAlipayClient(
                aliPayConfig.getGatewayUrl(),
                aliPayConfig.getAppId(),
                aliPayConfig.getAppPrivateKey(),
                "JSON", "utf-8",
                aliPayConfig.getAlipayPublicKey(),
                "RSA2");

        AlipayTradePagePayRequest req = new AlipayTradePagePayRequest();
        req.setNotifyUrl(aliPayConfig.getNotifyUrl());
        req.setReturnUrl("http://testshop.free.idcfengye.com/api/pay/return");

        String bizContent = "{"
                + "\"out_trade_no\":\"" + outTradeNo            + "\","
                + "\"total_amount\":\"" + amount.toPlainString() + "\","
                + "\"subject\":\"会员等级 " + level + " 购买\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\""
                + "}";

        req.setBizContent(bizContent);
        log.info("▶▶▶ MEMBER PAY Request outNo={} amount={}", outTradeNo, amount);

        return client.pageExecute(req).getBody();
    }

//    private String generateOrderSn() {
//        return UUID.randomUUID().toString().replaceAll("-", "");
//    }

    private String generatePaySn() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /** 给指定用户钱包 + amt（元） */
    private void creditWallet(Long userId, BigDecimal amt) {
        userProfileMapper.update(
                null,
                Wrappers.<UserProfile>lambdaUpdate()
                        .eq(UserProfile::getUserId, userId)
                        .setSql("wallet = COALESCE(wallet,0) + " + amt.intValue())
        );
    }

    private void handleMemberPaySuccess(MemberOrder order, BigDecimal amount) {
        // TODO: 在这里写会员生效、修改 member_orders 表等业务逻辑 😶😶😶😶😶😶

    }
}


